home *** CD-ROM | disk | FTP | other *** search
- == ASM KEYGEN TUTORIAL - WRITTEN BY TERAPHY [PC97]
- ===================================================
-
- This is the tools i use in this tutorial:
- Soft-Ice 3.01
- W32Dasm 8.9 *Regged*
- Tasm/Tlink
-
-
- Getting Started:
- What we should do is to get the registration code,
- find where the code is being calculated and rip it out.
- I will use two easy programs as examples,
- Command Line 97 1.0, and Flywheel V1.02b.
-
-
- Command Line 97 1.0:
- (http://www.odyssey.net/subscribers/js01/index.html)
- This program has a real simple code calculation.
- I will guide you step by step how to get the serial,
- how to rip it and how to make a working keygen.
-
- 1. Start the Program
-
- 2. Select Register
-
- 3. Go into Soft-Ice by pressing Ctrl-D, and set a breakpoint on
- GetDlgItemTextA. Type 'bpx getdlgitemtexta'. Now Press Ctrl-D
- again to get out from Soft-Ice.
-
- 4. Enter your name and a serial... I used 'TERAPHY' and '12345'
-
- 5. Press OK Button.. Soft-Ice will now show up inside the call
- to GetDlgItemTextA. Press F11 to get out of that call.
-
- Scroll up a bit and u will see this
-
- :0040254B 6A1E push 0000001E
- :0040254D 68300B4100 push 00410B30
- :00402552 68F0030000 push 000003F0
- :00402557 56 push esi
- :00402558 FF1550234100 Call [USER32!GetDlgItemTextA]
-
- The memory location being pushed at 40254D is where your name is
- stored. Type 'd 410B30', and you should see your name.
-
- Below this you'll see
-
- :0040255E 6A00 push 00000000
- :00402560 BF300B4100 mov edi, 00410B30
- :00402565 6A00 push 00000000
- :00402567 68FC030000 push 000003FC
- :0040256C 56 push esi
- :0040256D FF1518234100 Call [USER32!GetDlgItemInt]
-
- Step until you reach 40256D. The call to Getdlgitemint returns
- what you typed in as serial in eax. Type '? eax' and you will
- see this '00003039 0000012345 "09"'. 3039 is 12345 in hex.
- Also notice :00402560. This command moves the offset of your name
- into edi.
-
- Below this, you will see
-
- :00402573 B9FFFFFFFF mov ecx, FFFFFFFF
- :00402578 A354A54000 mov dword ptr [0040A554], eax
- :0040257D 2BC0 sub eax, eax
- :0040257F F2 repnz
- :00402580 AE scasb
- :00402581 F7D1 not ecx
- :00402583 49 dec ecx
-
- :00402578 saves your code for later use.
- The rest of the code is used to calculate the string length of
- your name... After this has been executed ecx contains the length
- of your name. In my case '7'.
-
- Below this, you'll see
-
- :00402584 0FBE05300B4100 movsx eax, byte ptr [00410B30]
- :0040258B 0FAFC8 imul ecx, eax
- :0040258E C1E10A shl ecx, 0A
- :00402591 81C1CCF80200 add ecx, 0002F8CC
- :00402597 890D50A54000 mov dword ptr [0040A550], ecx
- :0040259D 390D54A54000 cmp dword ptr [0040A554], ecx
-
- :00402584 moves the byte of the first letter to eax.
- In my case 54('T'). The next line multiplys eax (54),
- with ecx (7). shl ecx, 0A means multiply ecx with 2^10.
- And finnaly we add 02F8CC to ecx.
- At :0040259D the registration code is compared with what
- we typed in, remember it moved our code to [0040A554].
- Type '? ecx' and you can see your real code.
- But we don't just want the code, do we?
- Leave SoftIce and exit Command Line 97.
-
- 6. Start W32Dasm, and dissasemble cline97.exe
- Save dissasembly to file and exit.
-
- 7. Now we are going to build the keygen itself.
- Start your favorite texteditor and enter this code.
-
-
- Code Segment Byte Public
- Assume Ds:Code,Cs:Code
- Org 100h
- P386 ; this enables 386 instructions
- and 32bit registers
-
- Start:
-
- mov ah,09
- mov dx,offset Intro
- int 21h ; Show intro msg
-
- mov ah,0Ah
- mov dx,offset Namesto
- int 21h ; Get name
-
-
- Now load the dissasembly (cline97.alf) into your texteditor.
- Goto :00402573. Copy all code from here down to :00402591,
- and paste it into your asm source.
-
- It will look like this
- :00402573 B9FFFFFFFF mov ecx, FFFFFFFF
- :00402578 A354A54000 mov dword ptr [0040A554], eax
- :0040257D 2BC0 sub eax, eax
- :0040257F F2 repnz
- :00402580 AE scasb
- :00402581 F7D1 not ecx
- :00402583 49 dec ecx
- :00402584 0FBE05300B4100 movsx eax, byte ptr [00410B30]
- :0040258B 0FAFC8 imul ecx, eax
- :0040258E C1E10A shl ecx, 0A
- :00402591 81C1CCF80200 add ecx, 0002F8CC
-
- Now you can start ripping. You should remove everything except the command
- itself. The line :00402578 is obviously not needed, because it saves the
- inputed regcode for later use, and our keygen does not prompt for regcode,
- it calculates =)
-
- The source in your program should look like this.
-
- mov ecx, FFFFFFFF
- sub eax, eax
- repnz
- scasb
- not ecx
- dec ecx
- movsx eax, byte ptr [00410B30]
- imul ecx, eax
- shl ecx, 0A
- add ecx, 0002F8CC
-
- If you remember, it moved the offset of Name into edi earlier.
- So we need to add this before mov ecx, FFFFFFFF
- xor edi,edi
- mov di, offset Namesto+2 ; this must be +2, becaue that's there
- ; the actuall name begins.
-
- The command mov ecx, FFFFFFFF can't be compiled this way, so we
- have to change it to mov ecx, 0FFFFFFFFh.
-
- movsx eax, byte ptr [00410B30] is not valid either, because
- our name is'nt on [00410B30]. This could be changed to
- xor edi,edi
- mov di, offset Namesto+2
- movsx eax, byte ptr [edi]
-
- Both 'shl ecx, 0A' and 'add ecx, 0002F8CC' needs to be changed to
- valid hex format: 'shl ecx, 0Ah' and 'add ecx 2F8CCh'
-
- We now have a source that should look like this
-
- xor edi,edi
- mov di,offset Namesto+2
- mov ecx, 0FFFFFFFFh
- sub eax, eax
- repnz
- scasb
- not ecx
- dec ecx
- xor edi,edi
- mov di,offset Namesto+2
- movsx eax, byte ptr [edi]
- imul ecx, eax
- shl ecx, 0Ah
- add ecx, 2F8CCh
-
- after the dec ecx, we need to add another dec ecx,
- because when we enter our name, the last char will not be,
- in my case, 'y', it will be 0Dh, the enter key.
- This function, as it is, will return, in my case, ecx=8,
- not ecx=7 as it should be.
-
- movsx eax, byte ptr [edi] moves the ascii code of the first
- letter to eax. But, what if the user enters a name with a
- small letter? The input box in Command Line 97 automaticly
- makes it capital letters. This could be fixed by adding this
- code below movsx eax, byte ptr [edi].
-
- cmp eax, 061h ; compare eax with 61h (a)
- jb capital ; jump if below
- cmp eax, 07Ah ; compare eax with 7Ah (z)
- ja capital ; jump if above
- sub eax,20h ; convert char to capital
- capital:
-
- Our code now looks like
-
- Code Segment Byte Public
- Assume Ds:Code,Cs:Code
- Org 100h
- P386 ; this enables 386 instructions
- and 32bit registers
-
- Start:
-
- mov ah,09
- mov dx,offset Intro
- int 21h ; Show intro msg
-
- mov ah,0Ah
- mov dx,offset Namesto
- int 21h ; Get name
-
- xor edi,edi
- mov di,offset Namesto+2
- mov ecx, 0FFFFFFFFh
- sub eax, eax
- repnz
- scasb
- not ecx
- dec ecx
- dec ecx
- xor edi,edi
- mov di,offset Namesto+2
- movsx eax, byte ptr [edi]
- cmp eax, 061h
- jb capital
- cmp eax, 07Ah
- ja capital
- sub eax,20h
- capital:
- imul ecx, eax
- shl ecx, 0Ah
- add ecx, 2F8CCh
-
- What we need now is a routine to show the serial.
- We know that the serial is the decimal value of ecx.
-
- xor esi,esi
- mov si,offset Serial+9 ; esi is the offset there the
- ; regnumber will be stored
-
- mov eax,ecx ; eax should be reg number
- mov ecx,0Ah
- KeepGoing:
- xor edx,edx
- div ecx
- add dl,30h
- cmp dl,3Ah
- jl printnow
- add dl,7
- printnow:
- dec esi
- mov [esi],dl
- or eax,eax
- jnz keepgoing
-
- After this serial contains the registration code.
- You don't really need to understand this code. It can be used
- by any keygen there the code is the decimal value of a register.
-
- The only thing left to do is to add the command that's writes
- this to screen.
-
- mov ah, 9
- mov dx, offset RegPrompt
- int 21h
-
- And finnaly quit.
- int 20h
-
- The full source should look like this
-
- ; COMMAND LINE 97 *KEYGEN*
- ; CODED BY TERAPHY [PC97]
-
- Code Segment Byte Public
- Assume Ds:Code,Cs:Code
- Org 100h
- P386 ; this enables 386 instructions
- ; and 32bit registers
-
- Start:
-
- mov ah,09
- mov dx,offset Intro
- int 21h ; Show intro msg
-
- mov ah,0Ah
- mov dx,offset Namesto
- int 21h ; Get name
-
- xor edi,edi
- mov di,offset Namesto+2
- mov ecx, 0FFFFFFFFh
- sub eax, eax
- repnz
- scasb
- not ecx
- dec ecx
- xor edi,edi
- mov di,offset Namesto+2
- movsx eax, byte ptr [edi]
- cmp eax, 061h
- jb capital
- cmp eax, 07Ah
- ja capital
- sub eax,20h
- capital:
- imul ecx, eax
- shl ecx, 0Ah
- add ecx, 2F8CCh
-
- xor esi,esi
- mov si,offset Serial+9
- mov eax,ecx
- mov ecx,0Ah
- KeepGoing:
- xor edx,edx
- div ecx
- add dl,30h
- cmp dl,3Ah
- jl printnow
- add dl,7
- printnow:
- dec esi
- mov [esi],dl
- or eax,eax
- jnz keepgoing
-
- mov ah, 9
- mov dx, offset RegPrompt
- int 21h
-
- int 20h
-
- Intro db 13,10,'COMMAND LINE 97 *KEYGEN*'
- db 13,10,'CODED BY TERAPHY [PC97]',13,10
- db 13,10,'Enter your name: $'
-
- RegPrompt db 13,10,'Your registration key is: '
- Serial db 0,0,0,0,0,0,0,0,0,0,13,10,24h
-
- Namesto db 18h,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
- Code Ends
- End Start
-
- 8. Compile the code with tasm.
- tasm keygen.asm
- tlink /t keygen.asm
- You must link with the /t option for the keygen to run,
- it makes it a com file.
-
- 9. Congratulations! You have just made your first(?) keygen!
-
-
- Flywheel V1.02b
- (http://www.plannetarium.com)
-
- 1. Start the Program
-
- 2. Select Register
-
- 3. Go into Soft-Ice by pressing Ctrl-D, and set a breakpoint on
- GetDlgItemTextA. Type 'bpx getdlgitemtexta'. Now Press Ctrl-D
- again to get out from Soft-Ice.
-
- 4. Enter your name ('TERAPHY') and any serial ('12345').
- Press OK button, and Soft-Ice will show up.
-
- Scroll up a little bit and you'll see this
-
- :00402ACD 8D4C242C lea ecx, [esp+2C]
- :00402AD1 66AB stosw
- :00402AD3 6800010000 push 00000100
- :00402AD8 51 push ecx
- :00402AD9 6A65 push 00000065
- :00402ADB 56 push esi
- :00402ADC AA stosb
- :00402ADD FF151C154100 Call [USER32!GetDlgItemTextA]
-
- The important adress is there your name is being pushed, and
- that is push ecx. ecx got is value from 'lea ecx,[esp+2C]'.
- Type 'd esp+2c', and you should see your name.
-
- Below is a call to GetDlgItemInt, and as you remember it returns
- the inputed value to eax. Type '? eax' to see the serial you wrote.
-
- Below this, you'll see this
-
- :00402AF3 8D54242C lea edx, [esp+2C]
- :00402AF7 50 push eax
- :00402AF8 52 push edx
- :00402AF9 E8D2F9FFFF call 004024D0
- :00402AFE 83C408 add esp, 00000008
- :00402B01 85C0 test eax, eax
-
- 'lea edx,[esp+2C]' moves the offset of your name into edx,
- and then it pushes to stack. And eax contains our serial.
- And after the call it tests if eax is true or false.
- This call is there the registration code is being calculated.
-
- We trace into it. Step past the first instructions until you reach
-
- :004024EF B81F85EB51 mov eax, 51EB851F
- :004024F4 F7E7 mul edi
- :004024F6 C1EA05 shr edx, 05
- :004024F9 52 push edx
- :004024FA 56 push esi
- :004024FB E8B0000000 call 004025B0
-
- 004024EF - 004024F6 makes edx all digits except the two last
- of what we typed in as serial. If you wrote '12345' edx will
- be '123', and if you wrote '072597' edx will be '0725'.
-
- Then it pushes edx and esi. esi is the offset to your name.
- Trace into the call. Step past a few instructions until you reach
-
- :004025B8 8A06 mov al, byte ptr [esi]
- esi contains the offset to your name, so this instrucion moves
- the ascii code of the first letter to al, in my case '54'
-
- :004025BA 84C0 test al, al
- :004025BC 7426 je 004025E4
- This instrucions checks if we have inputed any name, if not it jumps.
-
- :004025BE 0FBEC0 movsx eax, al
- This instrucion moves al, to eax. If eax = FFFFFF54,
- after this eax would have been 00000054
-
- :004025C1 50 push eax
- :004025C2 E889140000 call 00403A50
- At a first look this call only moves the eax value to ecx.
- But it does also check for a space (20h) in eax. It returns
- false if not a space.
-
- :004025C7 83C404 add esp, 00000004
- This code changes the stack and should be ignored
-
- :004025CA 85C0 test eax, eax
- :004025CC 750E jne 004025DC
- Test if a space was found. Jump if found.
-
- :004025CE 0FBE0E movsx ecx, byte ptr [esi]
- This moves the letter into ecx (there it should already be).
-
- :004025D1 51 push ecx
- :004025D2 E8E9120000 call 004038C0
- If you, as in my case, wrote your name with a capital letter,
- this call will return eax = ascii code for your letter + 20h.
- This means it has been converted to a small letter.
-
- :004025D7 83C404 add esp, 00000004
- Ignore this
-
- :004025DA 03F8 add edi, eax
- Add edi, eax. Eax is the value of our char as small letter.
-
- :004025DC 8A4601 mov al, byte ptr [esi+01]
- :004025DF 46 inc esi
- Moves the value of the next char into al
-
- :004025E0 84C0 test al, al
- :004025E2 75DA jne 004025BE
- Test if al is 0. This means the end of our name has been reached.
- Jump if al is not 0.
-
- What this code has done, as you probably already figured out, is
- add the ascii value of all chars into edi. Except spaces (20h).
- It has also converted all capital chars into small letters.
-
- :004025E4 8B4C2410 mov ecx, [esp+10]
- This moves what we typed in (except the last two digits) into ecx
-
- :004025E8 8D14BF lea edx, [edi+4*edi]
- :004025EB 2BCF sub ecx, edi
- :004025ED 8D1457 lea edx, [edi+2*edx]
- :004025F0 85D2 test edx, edx
- :004025F2 740F je 00402603
- :004025F4 B8ABAAAAAA mov eax, AAAAAAAB
- :004025F9 F7E2 mul edx
- :004025FB D1EA shr edx, 1
- :004025FD 81C204060200 add edx, 00020604
- :00402603 33C0 xor eax, eax
- :00402605 3BCA cmp ecx, edx
-
- This code checks if you typed in the right number.
- At 402605 the compare is made. But ecx is no longer
- what we wrote as serial, because of the 'sub ecx,edi'
- command. We could make a simple equation of this.
-
- Assume X is our registration code (except the two digits).
- 'X - EDI = EDX'
-
- Now type '? edx+edi' and, in my case, I'll get '136182'
- as decimal value. This is my regcode, except the two last
- digits. These digits could be anything.
- Now then we know my registration code is '13618200',
- we can start on the keygen.
-
- 5. Run W32Dasm and dissasemble flywheel.exe (the file is located
- in 'C:\Program Files\Plannet Crafters\Flywheel')
- Save the dissasembly to disk and quit.
-
- 6. Now it's time to start on the code. We can use the same start
- as in the last keygen. We go directly to the ripping part.
-
- You can start by copy all code from 4025B8 to 402605 into your program.
- That will look like this.
-
- :004025B8 8A06 mov al, byte ptr [esi]
- :004025BA 84C0 test al, al
- :004025BC 7426 je 004025E4
- :004025BE 0FBEC0 movsx eax, al
- :004025C1 50 push eax
- :004025C2 E889140000 call 00403A50
- :004025C7 83C404 add esp, 00000004
- :004025CA 85C0 test eax, eax
- :004025CC 750E jne 004025DC
- :004025CE 0FBE0E movsx ecx, byte ptr [esi]
- :004025D1 51 push ecx
- :004025D2 E8E9120000 call 004038C0
- :004025D7 83C404 add esp, 00000004
- :004025DA 03F8 add edi, eax
- :004025DC 8A4601 mov al, byte ptr [esi+01]
- :004025DF 46 inc esi
- :004025E0 84C0 test al, al
- :004025E2 75DA jne 004025BE
- :004025E4 8B4C2410 mov ecx, dword ptr [esp+10]
- :004025E8 8D14BF lea edx, dword ptr [edi+4*edi]
- :004025EB 2BCF sub ecx, edi
- :004025ED 8D1457 lea edx, dword ptr [edi+2*edx]
- :004025F0 85D2 test edx, edx
- :004025F2 740F je 00402603
- :004025F4 B8ABAAAAAA mov eax, AAAAAAAB
- :004025F9 F7E2 mul edx
- :004025FB D1EA shr edx, 1
- :004025FD 81C204060200 add edx, 00020604
- :00402603 33C0 xor eax, eax
- :00402605 3BCA cmp ecx, edx
-
- Here is how I would have ripped this into the program,
- with comments.
-
- ; THIS REPLACES 4025BE - 4025E2
-
- xor ecx,ecx
- xor edi,edi
- mov di, offset NameSto+2 ; Mov the offset of your name
- ; into edi
- anotherchar:
- movsx eax, byte ptr [di] ; Get char from [di]
-
- cmp eax, 20h ; Compare your letter with 20h
- je space ; Jump if equal
-
- cmp eax, 041h ; Compare your letter to see
- jb capital ; if it's already is a
- cmp eax, 05Ah ; small lettter
- ja capital
- add eax,20h ; If capital char, add 20h to make
- ; it a small letter.
- capital:
- add ecx, eax ; add eax to ecx, if not space
- space:
-
- inc di ; inc di to make it point to the
- ; next char.
-
- cmp byte ptr [di], 0dh ; Compare next char with 0Dh (return)
- ; Remember then we get our name, it
- ; ends with a 0Dh
-
- jne anotherchar ; Jump if not 0Dh
- mov edi, ecx
-
- ; CODE BELOW REPLACES 4025E2 - 402603
- ; All commands with ecx (our inputed code) is not needed
- ; because we do not input any code.
-
- xor edx,edx
- lea edx, [edi + 4*edi]
- lea edx, [edi + 2*edx]
- mov eax, 0AAAAAAABh
- mul edx
- shr edx, 1
- add edx, 20604h
-
- xor ecx, ecx ; Here we do our equation
- add ecx, edx ;
- add ecx, edi ; ecx = edx + edi
-
- After this, ecx contains the regcode.
- The complete source could look like this.
-
- Code Segment Byte Public
- Assume Ds:Code,Cs:Code
- Org 100h
- P386
-
- Start:
-
- mov ah,09
- mov dx,offset Intro
- int 21h ; Show intro msg
-
- mov ah,0Ah
- mov dx,offset Namesto
- int 21h ; Get name
-
- xor ecx,ecx
- xor edi,edi
- mov di, offset NameSto+2
- anotherchar:
- movsx eax, byte ptr [di]
- cmp eax, 20h
- je space
- cmp eax, 041h
- jb capital
- cmp eax, 05Ah
- ja capital
- add eax,20h
- capital:
- add ecx, eax
- space:
- inc di
- cmp byte ptr [di], 0dh
- jne anotherchar
- mov edi, ecx
- xor edx,edx
- lea edx, [edi + 4*edi]
- lea edx, [edi + 2*edx]
- mov eax, 0AAAAAAABh
- mul edx
- shr edx, 1
- add edx, 20604h
- xor ecx, ecx
- add ecx, edx
- add ecx, edi
-
- xor esi,esi
- mov si,offset Serial+9
- mov eax,ecx
- mov ecx,0Ah
- KeepGoing:
- xor edx,edx
- div ecx
- add dl,30h
- cmp dl,3Ah
- jl printnow
- add dl,7
- printnow:
- dec esi
- mov [esi],dl
- or eax,eax
- jnz keepgoing
-
- mov ah, 9
- mov dx, offset RegPrompt
- int 21h
-
- int 20h
-
- Intro db 13,10,'FLYWHEEL 1.2 *KEYGEN*'
- db 13,10,'CODED BY TERAPHY [PC97]',13,10
- db 13,10,'Enter your name: $'
-
- RegPrompt db 13,10,'Your registration key is: '
- Serial db 0,0,0,0,0,0,0,0,0,'0','0',13,10,24h
-
- Namesto db 18h,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
- Code Ends
- End Start
-
-
- Now compile, run and enjoy! :)
-
-
- ==================
- = TERAPHY [PC97] =
- = 07/25/1997 =
- ==================